home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Belgian Amiga Club - ADF Collection
/
BS1 part 41.zip
/
BS1 part 41
/
Compute`s Amiga resource 1.adf
/
Source
/
ALC
/
advgraph.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-07
|
32KB
|
1,053 lines
/* Advanced Laser Chess graphics routines */
#include "advlaser.h"
#include <hardware/blit.h>
#include "advsound.h"
#define WAITTIME 3L /* Used with Delay() */
/* External variables */
extern int gate[4]; /* ADVLASER.C */
extern ULONG grid[GRIDX][GRIDY]; /* ADVLASER.C */
extern struct explosion_struct explode_info[MAXEXPLOSIONS]; /* ADVLASER.C */
extern int turn; /* ADVLASER.C */
extern int moves_left; /* ADVLASER.C */
extern unsigned long grid[15][11]; /* ADVLASER.C */
extern int selected_x, selected_y; /* ADVLASER.C */
extern BOOL select_flag; /* ADVLASER.C */
extern int background_on, background_period, background_channel; /* ADVSOUND.C */
extern struct TextAttr font; /* ADVLASER.C */
/* Local variables */
struct BitMap *current_bitmap; /* Current bitmap to draw in */
struct BitMap image_bitmap; /* Image bitmap (contains piece images) */
struct BitMap primary_bitmap; /* Primary screen */
struct BitMap backup_bitmap; /* Used for miscellaneous purposes */
struct BitMap mask_bitmap; /* Used for image masks */
struct Screen *screen;
struct NewScreen screen_def =
{
0, 0, SCREENX, SCREENY, PLANES, /* Left, Top, width, height, depth */
0, 0, /* Detail/Block pens */
NULL, /* Display mode */
CUSTOMSCREEN | CUSTOMBITMAP, /* Screen type */
&font, /* Font pointer */
NULL, /* Screen title */
NULL, NULL /* No special gadgets; bitmap is set below */
};
struct Window *window;
struct NewWindow window_def =
{
0, 0, SCREENX, SCREENY, /* X, Y, width, height */
0, 1, /* Detail/block pen */
MOUSEBUTTONS | RAWKEY, /* IDCMP flags */
RMBTRAP | NOCAREREFRESH | SMART_REFRESH | ACTIVATE | BORDERLESS, /* Flags */
NULL, /* First gadget */
NULL, /* Check mark */
NULL, /* Title */
NULL, /* Screen - set later */
NULL, /* Bitmap */
0, 0, 0, 0, /* Min & Max Width & Height */
CUSTOMSCREEN /* Screen type */
};
draw_grid()
{
int x, y, d;
draw_icons();
draw_border();
for(x=0;x<15;x++)
for(y=0;y<11;y++)
{
draw_square(x, y);
draw_piece(x, y, NORMAL);
}
if(select_flag)
highlight_square(selected_x, selected_y, NORMAL);
}
draw_piece(x, y, flag)
register int x, y, flag;
{
int x_src, y_src; /* X and Y positions of piece in piece screen */
int i;
/* Return if nothing at (x, y) or if it's a grid gate or hypersquare */
if(grid[x][y] == 0L || grid[x][y] == OTHER) return;
/* Get coordinates of piece in piece screen, return if can't draw. */
if(!get_piece_coords(x, y, &x_src, &y_src)) return;
/* Highlight the piece if stunned and if it isn't being drawn as hyperee. */
if(!(grid[x][y] & ALIVE) && !(flag & HYPEREE))
{
flag |= HIGHLIGHT;
flag &= ~NORMAL;
}
/* Draw piece with optional shadow... */
if(flag & NORMAL)
draw_normal(x_src, y_src, x, y, flag & NOSHADOW? FALSE : TRUE);
else if(flag & HIGHLIGHT || flag & HYPEREE)
draw_special(x_src, y_src, x, y, flag, flag & NOSHADOW? FALSE : TRUE);
}
/* Computes coordinates of piece in the image screen. */
get_piece_coords(x, y, x_src, y_src)
register int x, y, *x_src, *y_src;
{
unsigned long id, obj;
obj = grid[x][y];
id = grid[x][y] & 0x1FFFFFFE; /* Mask off rotation and ALIVE bits */
/* Mask off FIRED, HYPERED, and CRUNCHED bits on lasers, hypergons, kings,
* and crunching octagons */
if(id & (KILLLASER | STUNLASER | KING | HYPERGON | PARTOCTAGON | FULLOCTAGON))
id = id & ~FIRED;
/* If I had the time, all of these numbers would be define statements
* for more flexible programming, but alas... */
switch(id)
{
case STUNLASER | RED:
*x_src = facing(obj) << 4; *y_src = 1; break;
case STUNLASER | GREEN:
*x_src = (facing(obj) << 4) + 128; *y_src = 1; break;
case BOMB | RED:
*x_src = 256; *y_src = (int)facing(obj) * 18 + 1; break;
case BOMB | GREEN:
*x_src = 272; *y_src = (int)facing(obj) * 18 + 1; break;
case FULLOCTAGON | RED:
*x_src = 288; *y_src = 19; break;
case FULLOCTAGON | GREEN:
*x_src = 288; *y_src = 1; break;
case PARTOCTAGON | RED:
*x_src = facing(obj) << 4; *y_src = 19; break;
case PARTOCTAGON | GREEN:
*x_src = (facing(obj) << 4) + 128; *y_src = 19; break;
case ONEWAYMIRROR | RED:
*x_src = facing(obj) << 4; *y_src = 37; break;
case ONEWAYMIRROR | GREEN:
*x_src = (facing(obj) << 4) + 128; *y_src = 37; break;
case TRIMIRROR | RED:
*x_src = facing(obj) << 4; *y_src = 55; break;
case TRIMIRROR | GREEN:
*x_src = (facing(obj) << 4) + 128; *y_src = 55; break;
case KILLLASER | RED:
*x_src = facing(obj) << 4; *y_src = 73; break;
case KILLLASER | GREEN:
*x_src = (facing(obj) << 4) + 128; *y_src = 73; break;
case SPLITTER | RED:
*x_src = facing(obj) << 4; *y_src = 91; break;
case SPLITTER | GREEN:
*x_src = (facing(obj) << 4) + 128; *y_src = 91; break;
case KING | RED:
*x_src = 256; *y_src = 37; break;
case KING | GREEN:
*x_src = 272; *y_src = 37; break;
case HYPERGON | RED:
*x_src = 256; *y_src = 55; break;
case HYPERGON | GREEN:
*x_src = 272; *y_src = 55; break;
default: return(FALSE); break; /* Can't draw any of the above */
}
return(TRUE); /* Indicate acknowledgement */
}
/* Draws a piece with optional shadow */
draw_normal(x_src, y_src, x, y, shadow)
register int x_src, y_src, x, y, shadow;
{
int i;
if(shadow)
{
draw_mask(x_src, y_src, x * GRIDSQUAREWIDTH + GRIDLEFT - 1,
y * GRIDSQUAREHEIGHT + GRIDTOP + 1,
GRIDSQUAREWIDTH, GRIDSQUAREHEIGHT, SHADOW);
}
/* Copy piece's mask to currently displayed bitmap */
draw_mask(x_src, y_src, x * GRIDSQUAREWIDTH + GRIDLEFT,
y * GRIDSQUAREHEIGHT + GRIDTOP,
GRIDSQUAREWIDTH, GRIDSQUAREHEIGHT, NORMAL);
/* Copy source image to destination bitmap */
BltBitMap(&image_bitmap, (long)x_src, (long)y_src, current_bitmap,
(long)(x * GRIDSQUAREWIDTH + GRIDLEFT), (long)(y * GRIDSQUAREHEIGHT +
GRIDTOP), (long)GRIDSQUAREWIDTH, (long)GRIDSQUAREHEIGHT,
ABNC|ANBC, -1L, NULL);
}
/* Draws a highlighted piece or a hyperee, depending on flag. */
draw_special(x_src, y_src, x, y, flag, shadow)
register int x_src, y_src, x, y, flag, shadow;
{
int i;
if(shadow)
{
draw_mask(x_src, y_src, x * GRIDSQUAREWIDTH + GRIDLEFT - 1,
y * GRIDSQUAREHEIGHT + GRIDTOP + 1,
GRIDSQUAREWIDTH, GRIDSQUAREHEIGHT, SHADOW);
}
draw_mask(x_src, y_src, x * GRIDSQUAREWIDTH + GRIDLEFT,
y * GRIDSQUAREHEIGHT + GRIDTOP,
GRIDSQUAREWIDTH, GRIDSQUAREHEIGHT, NORMAL);
if(flag & HIGHLIGHT) /* If piece is to be drawn highlighted... */
{
/* Draw as a white (highlight color) piece */
draw_mask(x_src, y_src, x * GRIDSQUAREWIDTH + GRIDLEFT,
y * GRIDSQUAREHEIGHT + GRIDTOP,
GRIDSQUAREWIDTH, GRIDSQUAREHEIGHT, HIGHLIGHT);
}
else if(flag & HYPEREE)
{
/* Draw piece in fade color */
draw_mask(x_src, y_src, x * GRIDSQUAREWIDTH + GRIDLEFT,
y * GRIDSQUAREHEIGHT + GRIDTOP,
GRIDSQUAREWIDTH, GRIDSQUAREHEIGHT, HYPEREE);
}
}
/* type can be equal to SHADOW, HIGHLIGHT, NORMAL, or HYPEREE. */
draw_mask(sx, sy, dx, dy, w, h, type)
int sx, sy, dx, dy, w, h, type;
{
register int mask, ih, ip, offset;
int ww, iw, i;
ww = (w + 15) >> 4; /* Word width */
/* Copy source image into mask bitmap */
BltBitMap(&image_bitmap, (long)sx, (long)sy, &mask_bitmap, 0L, 0L,
(long)w, (long)h, 0xC0L, -1L, NULL);
/* For each word, or all bits in all planes for that word */
for(iw=0; iw < ww; iw++) /* Word width loop */
for(ih=0; ih < h; ih++) /* Height */
{
mask = 0;
offset = (iw << 1) + (ih * ww << 1);
for(ip=0; ip < PLANES; ip++) /* Number of planes */
mask |= *((UWORD *)(mask_bitmap.Planes[ip] + offset));
for(ip=0; ip < PLANES; ip++)
*((UWORD *)(mask_bitmap.Planes[ip] + offset)) = mask;
}
/* "Punch a hole" through the playfield */
BltBitMap(&mask_bitmap, 0L, 0L, current_bitmap, (long)dx, (long)dy,
(long)w, (long)h, ANBC, -1L, NULL);
if(type != NORMAL)
{
for(iw=0; iw < ww; iw++) /* Word width loop */
for(ih=0; ih < h; ih++) /* Height */
{
offset = (iw << 1) + (ih * ww << 1);
if(type == SHADOW)
*((UWORD *)(mask_bitmap.Planes[0] + offset)) = 0;
else if(type == HIGHLIGHT)
for(i=1; i<PLANES; i++)
*((UWORD *)(mask_bitmap.Planes[i] + offset)) = 0;
else if(type == HYPEREE)
{
*((UWORD *)(mask_bitmap.Planes[0] + offset)) = 0;
*((UWORD *)(mask_bitmap.Planes[3] + offset)) = 0;
}
}
BltBitMap(&mask_bitmap, 0L, 0L, current_bitmap, (long)dx, (long)dy,
(long)w, (long)h, ABNC|ANBC, -1L, NULL);
}
}
animate_explosion(num_expl, explpx, explpy, explxv, explyv)
int *explpx, *explpy, *explxv, *explyv;
register int num_expl;
{
int i, j, flash_index = 100, el, tx, ty, d;
int pix_save[EXPPTS];
for(i=0; i<EXPPTS; i++)
pix_save[i] = ReadPixel(&screen->RastPort, (long)explpx[i], (long)explpy[i]);
for(el=0; el<EXPLOSIONDISTANCE; el++) /* # of times to move points */
{
--flash_index;
for(i=0; i<EXPPTS; i++)
{
if(pix_save[i] != -1) /* If pixel is to be restored... */
{
SetAPen(&screen->RastPort, (long)pix_save[i]);
WritePixel(&screen->RastPort, (long)explpx[i], (long)explpy[i]);
}
tx = explpx[i] + explxv[i]; /* Find next location of pixel */
ty = explpy[i] + explyv[i];
/* If pixel is within grid boundary... */
if(tx > GRIDLEFT && tx < GRIDRIGHT && ty > GRIDTOP && ty < GRIDBOTTOM)
{
explpx[i] = tx; /* Update coordinates of pixel */
explpy[i] = ty;
}
else /* If pixel's next position is out of grid boundary... */
{
if(tx <= GRIDLEFT || tx >= GRIDRIGHT) /* If hit left or right edge... */
explxv[i] = -explxv[i]; /* Negate x velocity */
if(ty <= GRIDTOP || ty >= GRIDBOTTOM) /* If hit top or bottom... */
explyv[i] = -explyv[i]; /* Negate y velocity */
}
if(rnd(100) < flash_index)
{
/* Check value under new pixel location */
d = ReadPixel(&screen->RastPort, (long)explpx[i], (long)explpy[i]);
/* If the same color as another pixel, set flag to indicate not to draw next loop */
if(d == WHITE) pix_save[i] = -1;
else pix_save[i] = d; /* Otherwise, restore with this color */
SetAPen(&screen->RastPort, WHITE); /* Plot new pixel */
WritePixel(&screen->RastPort, (long)explpx[i], (long)explpy[i]);
}
else pix_save[i] = -1;
}
}
for(i=0; i<EXPPTS; i++)
if(pix_save[i] != -1) /* If pixel is to be restored... */
{
SetAPen(&screen->RastPort, (long)pix_save[i]);
WritePixel(&screen->RastPort, (long)explpx[i], (long)explpy[i]);
}
}
draw_border()
{
struct RastPort *r;
/* Could use DrawBorder() for this, but what the heck... */
r = &screen->RastPort;
SetAPen(r, GRID_BORDER_COLOR);
SetDrMd(r, JAM1);
Move(r, (long)(GRIDLEFT - 1), (long)(GRIDTOP - 1));
Draw(r, (long)(GRIDRIGHT + 1), (long)(GRIDTOP - 1));
Draw(r, (long)(GRIDRIGHT + 1), (long)(GRIDBOTTOM + 1));
Draw(r, (long)(GRIDLEFT - 1), (long)(GRIDBOTTOM + 1));
Draw(r, (long)(GRIDLEFT - 1), (long)(GRIDTOP - 1));
/* Draw border shadow */
SetAPen(r, BLACK);
Move(r, (long)(GRIDLEFT - 2), (long)(GRIDTOP + 2));
Draw(r, (long)(GRIDLEFT - 2), (long)(GRIDBOTTOM + 2));
Draw(r, (long)(GRIDRIGHT - 2), (long)(GRIDBOTTOM + 2));
}
draw_square(x, y)
int x, y;
{
int index;
if(x == GRIDX / 2 && y & 1) /* If drawing on grid gate or hypersquare... */
if(y & 1)
{
switch(y)
{
case 1: index = 0; break;
case 3: index = 1; break;
case 7: index = 2; break;
case 9: index = 3; break;
default: index = 0; break; /* Dummy value; doesn't really matter */
}
if(gate[index] == CLOSED || y == GRIDY / 2)
{ /* Draw empty square (with shadow) */
BltBitMap(&image_bitmap, (long)SP_EMPTYSQUAREX1,
(long)SP_EMPTYSQUAREY1, current_bitmap,
(long)(GRIDLEFT + (GRIDX / 2) * GRIDSQUAREWIDTH),
(long)(y * GRIDSQUAREHEIGHT + GRIDTOP),
(long)EMPTYSQUAREWIDTH, (long)EMPTYSQUAREHEIGHT,
BLIT_11_MINTERM, -1L, NULL);
return;
}
}
SetAPen(&screen->RastPort, (long)square_color(x, y));
SetDrMd(&screen->RastPort, JAM1);
RectFill(&screen->RastPort, (long)(x * GRIDSQUAREWIDTH + GRIDLEFT),
(long)(y * GRIDSQUAREHEIGHT + GRIDTOP),
(long)(x * GRIDSQUAREWIDTH + GRIDLEFT + GRIDSQUAREWIDTH - 1),
(long)(y * GRIDSQUAREHEIGHT + GRIDTOP + GRIDSQUAREHEIGHT - 1));
}
int square_color(x, y) /* Returns the color value of a specified square */
register int x, y;
{
register int col;
if(!(x & 1)) col = TRUE; /* Go through logic for correct color */
else col = FALSE;
if(y & 1) col = !col;
if(col) return(DARK_SQUARE);
else return(LIGHT_SQUARE);
}
/* possible = NORMAL if the square is to be highlighted for a specific
piece, POSSIBLE if the square is to be highlighted as a possible
movement destination indicator. */
highlight_square(gx, gy, possible)
register int gx, gy, possible;
{
int c;
if(possible == NORMAL)
SetAPen(&screen->RastPort, HIGHLIGHT_COLOR);
else
{
set_color(DARK_POSSIBLE, COLOR_POSSIBLE_DARK);
c = square_color(gx, gy) == LIGHT_SQUARE? LIGHT_POSSIBLE : DARK_POSSIBLE;
SetAPen(&screen->RastPort, (long)c);
}
RectFill(&screen->RastPort, (long)(gx * GRIDSQUAREWIDTH + GRIDLEFT),
(long)(gy * GRIDSQUAREHEIGHT + GRIDTOP),
(long)(gx * GRIDSQUAREWIDTH + GRIDLEFT + GRIDSQUAREWIDTH - 1),
(long)(gy * GRIDSQUAREHEIGHT + GRIDTOP + GRIDSQUAREHEIGHT - 1));
draw_piece(gx, gy, NORMAL);
}
/* Animates square dropping from grid and takes care of piece existing
* on square (if any). */
down_square(y)
register int y;
{
register int i, x_src = SP_GRIDGATEX1, y_src = SP_GRIDGATEY1;
int x_dest, y_dest;
x_dest = GRIDLEFT + (GRIDX / 2) * GRIDSQUAREWIDTH;
y_dest = y * GRIDSQUAREHEIGHT + GRIDTOP;
for(i=0; i<NUMSQUAREANIMS; i++)
{
BltBitMap(&image_bitmap, (long)x_src, (long)y_src, current_bitmap,
(long)x_dest, (long)y_dest, (long)GRIDGATEWIDTH,
(long)GRIDGATEHEIGHT, BLIT_11_MINTERM, -1L, NULL);
/* Superimpose piece about to be destroyed (if any) */
draw_piece(7, y, HIGHLIGHT | NOSHADOW);
Delay(WAITTIME);
/* Move over to next "frame" of animation sequence */
x_src += GRIDGATESPACE;
}
/* If there WAS a piece on that gate, it isn't there any longer. */
if(grid[GRIDX / 2][y])
{
BltBitMap(&image_bitmap, (long)SP_EMPTYSQUAREX1, (long)SP_EMPTYSQUAREY1,
current_bitmap, (long)x_dest, (long)y_dest, (long)EMPTYSQUAREWIDTH,
(long)EMPTYSQUAREHEIGHT, BLIT_11_MINTERM, -1L, NULL);
explode_info[0].flag = TRUE;
explode_info[0].x = GRIDX / 2;
explode_info[0].y = y;
explode();
}
/* Mark this position as OTHER for the purpose of prohibiting movement */
grid[7][y] = OTHER;
}
/* Animates a grid square coming up from nowhere */
up_square(y)
register int y;
{
register int i;
register int x_src = SP_GRIDGATEX1 + GRIDGATESPACE * (NUMSQUAREANIMS - 1);
register int y_src = SP_GRIDGATEY1;
int x_dest, y_dest;
x_dest = GRIDLEFT + (GRIDX / 2) * GRIDSQUAREWIDTH;
y_dest = y * GRIDSQUAREHEIGHT + GRIDTOP;
for(i=0; i<NUMSQUAREANIMS; i++)
{
BltBitMap(&image_bitmap, (long)x_src, (long)y_src, current_bitmap,
(long)x_dest, (long)y_dest, (long)GRIDGATEWIDTH,
(long)GRIDGATEHEIGHT, BLIT_11_MINTERM, -1L, NULL);
/* Superimpose piece about to be destroyed (if any) */
draw_piece(7, y, HIGHLIGHT | NOSHADOW);
Delay(WAITTIME);
/* Move over to next "frame" of animation sequence */
x_src -= GRIDGATESPACE;
}
grid[7][y] = 0L; /* Erase any ID that was at this position before */
}
down_hyper() /* Animates hypersquare disappearing */
{
register int i, x_src = SP_HYPERSQUAREX1, y_src = SP_HYPERSQUAREY1;
register int x_dest, y_dest;
x_dest = GRIDLEFT + (GRIDX / 2) * GRIDSQUAREWIDTH;
y_dest = (GRIDY / 2) * GRIDSQUAREHEIGHT + GRIDTOP;
for(i=0; i<NUMHYPERANIMS; i++)
{
BltBitMap(&image_bitmap, (long)x_src, (long)y_src, current_bitmap,
(long)x_dest, (long)y_dest, (long)HYPERSQUAREWIDTH,
(long)HYPERSQUAREHEIGHT, BLIT_11_MINTERM, -1L, NULL);
Delay(WAITTIME);
/* Move over to next "frame" of animation sequence */
x_src += HYPERSQUARESPACE;
}
}
up_hyper() /* Animates hypersquare appearing from nowhere */
{
register int i;
register int x_src = SP_HYPERSQUAREX1 + (NUMHYPERANIMS - 1) * HYPERSQUARESPACE;
register int y_src = SP_HYPERSQUAREY1;
register int x_dest, y_dest;
x_dest = GRIDLEFT + (GRIDX / 2) * GRIDSQUAREWIDTH;
y_dest = (GRIDY / 2) * GRIDSQUAREHEIGHT + GRIDTOP;
for(i=0; i<NUMHYPERANIMS; i++)
{
BltBitMap(&image_bitmap, (long)x_src, (long)y_src, current_bitmap,
(long)x_dest, (long)y_dest, (long)HYPERSQUAREWIDTH,
(long)HYPERSQUAREHEIGHT, BLIT_11_MINTERM, -1L, NULL);
Delay(WAITTIME);
/* Move over to previous "frame" of animation sequence */
x_src -= HYPERSQUARESPACE;
}
}
/* Fades out a piece drawn in the fade color and associates hyper sound with action */
hyper_out(x, y)
register int x, y;
{
int rgb, drgb, i, j;
/* Get RGB levels of square containing hyperee */
drgb = GetRGB4(screen->ViewPort.ColorMap, (long)square_color(x, y));
/* Get RGB levels of hyperee color */
hyperee_color(x, y);
rgb = GetRGB4(screen->ViewPort.ColorMap, FADE_COLOR);
hyper_out_sound();
for(i=0; i<COLORSHADES; i++)
{
Delay(WAITTIME);
adjust_rgb(&rgb, drgb);
set_color(FADE_COLOR, rgb);
}
}
hyper_in(x, y) /* Fades in a piece and associates hyper sound */
register int x, y;
{
UWORD rgb, drgb, i;
/* Get destination color (final fade color) of piece */
hyperee_color(x, y);
drgb = GetRGB4(screen->ViewPort.ColorMap, FADE_COLOR);
/* Get starting color of fading piece (same as the occupying square) */
rgb = GetRGB4(screen->ViewPort.ColorMap, (long)square_color(x, y));
set_color(FADE_COLOR, rgb);
draw_piece(x, y, HYPEREE); /* Draw piece in fade color WITH shadow */
hyper_in_sound();
for(i=0; i<COLORSHADES; i++)
{
Delay(WAITTIME);
adjust_rgb(&rgb, drgb);
set_color(FADE_COLOR, rgb);
}
draw_piece(x, y, NORMAL);
}
/* Sets FADE_COLOR depending on color of piece at (x, y) */
hyperee_color(x, y)
register int x, y;
{
register UWORD rgb;
if(grid[x][y] & RED) /* If piece at (x, y) is red... */
rgb = GetRGB4(screen->ViewPort.ColorMap, BRIGHT_RED);
else if(grid[x][y] & GREEN) /* If piece is green... */
rgb = GetRGB4(screen->ViewPort.ColorMap, BRIGHT_GREEN);
if(!(grid[x][y] & ALIVE)) /* Otherwise, piece must be white (stunned) */
rgb = GetRGB4(screen->ViewPort.ColorMap, WHITE);
set_color(FADE_COLOR, rgb);
}
adjust_rgb(rgb, drgb) /* Moves RGB values towards that in drgb */
UWORD *rgb, drgb;
{
if(RED_VALUE(*rgb) < RED_VALUE(drgb))
*rgb += 0x0100;
else if(RED_VALUE(*rgb) > RED_VALUE(drgb))
*rgb -= 0x0100;
if(GREEN_VALUE(*rgb) < GREEN_VALUE(drgb))
*rgb += 0x0010;
else if(GREEN_VALUE(*rgb) > GREEN_VALUE(drgb))
*rgb -= 0x0010;
if(BLUE_VALUE(*rgb) < BLUE_VALUE(drgb))
*rgb += 0x0001;
else if(BLUE_VALUE(*rgb) > BLUE_VALUE(drgb))
*rgb -= 0x0001;
}
fade() /* Fades pointer color and icons to green or red */
{
UWORD i, j, rgb[2], drgb[2];
rgb[0] = GetRGB4(screen->ViewPort.ColorMap, POINTERHIGHLIGHT); /* Highlight */
rgb[1] = GetRGB4(screen->ViewPort.ColorMap, POINTERBODY); /* Body */
if(turn == GREEN)
{
drgb[0] = GetRGB4(screen->ViewPort.ColorMap, BRIGHT_GREEN);
drgb[1] = GetRGB4(screen->ViewPort.ColorMap, GREEN_COLOR);
}
else
{
drgb[0] = GetRGB4(screen->ViewPort.ColorMap, BRIGHT_RED);
drgb[1] = GetRGB4(screen->ViewPort.ColorMap, RED_COLOR);
}
for(i=0; i<COLORSHADES; i++)
{
Delay(WAITTIME);
if(i & 1) modify_background_sound();
for(j=0; j<2; j++)
{
set_color(ICON_FADE_COLOR, rgb[1]); /* Fade icons to normal colors */
set_color(POINTERHIGHLIGHT, rgb[0]);
set_color(POINTERBODY, rgb[1]);
adjust_rgb(&rgb[0], drgb[0]);
adjust_rgb(&rgb[1], drgb[1]);
}
}
}
lower_shade(rgb) /* Fades color in rgb towards black one shade */
UWORD *rgb;
{
if(RED_VALUE(*rgb) > 0)
*rgb -= 0x0100;
if(GREEN_VALUE(*rgb) > 0)
*rgb -= 0x0010;
if(BLUE_VALUE(*rgb) > 0)
*rgb -= 0x0010;
}
/* Fades up all color registers to (TRUE) or from (FALSE) background color */
fade_all(to_background, modify_snd)
register int to_background, modify_snd;
{
register int i, j;
UWORD rgb[SCREENCOLORS], drgb[SCREENCOLORS];
static UWORD rgbsave[SCREENCOLORS];
static BOOL first = TRUE;
if(first) /* Make a local copy of the colors */
{
first = FALSE;
for(i=0; i<SCREENCOLORS; i++)
rgbsave[i] = GetRGB4(screen->ViewPort.ColorMap, (long)i);
}
for(i=0; i<SCREENCOLORS; i++)
{
drgb[i] = to_background? GetRGB4(screen->ViewPort.ColorMap, 0L) :
rgbsave[i];
rgb[i] = to_background? rgbsave[i] :
GetRGB4(screen->ViewPort.ColorMap, 0L);
}
for(i=0; i<COLORSHADES; i++)
{
if(background_on && modify_snd) /* If background sound is playing... */
modify_sound(background_channel, background_period, to_background?
BACKGROUND_VOLUME - (i + 1) / BACKGROUND_VOLUME :
(i + 1) / BACKGROUND_VOLUME);
Delay(WAITTIME);
for(j=0; j<SCREENCOLORS; j++)
{
adjust_rgb(&rgb[j], drgb[j]);
set_color((long)j, rgb[j]);
}
}
}
draw_moves(remaining)
register int remaining;
{
register int x;
SetAPen(&screen->RastPort, 0L); /* Background color */
RectFill(&screen->RastPort, (long)MOVESX1, (long)MOVESY1,
(long)(MOVESX1 + 1 + MOVEWIDTH * 3), (long)(MOVESY1 + MOVEHEIGHT));
if(remaining > 0)
{
x = remaining * MOVEWIDTH + (remaining - 1);
BltBitMap(&image_bitmap, (long)SP_MOVESX1, (long)SP_MOVESY1,
current_bitmap, (long)MOVESX1, (long)MOVESY1, (long)x,
(long)MOVEHEIGHT, BLIT_11_MINTERM, -1L, NULL);
}
}
/* Handles the display portion of the end of a game. The following
actions will be taken, depending on who gets blasted:
RED: grid squares and background color fade to shades of green.
GREEN: grid squares and background color fade to shades of red.
RED and GREEN: grid squares fade to alternating shades of green and
red (the normal dark squares turn to red, the light squares turn
to green), and the background color remains the same. */
end_game_display(id) /* The VICTIM's ID is passed to this routine. */
unsigned long id;
{
UWORD i, j, rgb[3], drgb[3]; /* [0]=dark square, [1]=light, [2]=background */
UWORD rgb_save[3];
/* Get current color settings */
rgb[0] = rgb_save[0] = GetRGB4(screen->ViewPort.ColorMap, DARK_SQUARE);
rgb[1] = rgb_save[1] = GetRGB4(screen->ViewPort.ColorMap, LIGHT_SQUARE);
rgb[2] = rgb_save[2] = GetRGB4(screen->ViewPort.ColorMap, BACKGROUND);
if((id & (GREEN | RED)) == GREEN) /* If green player loses... */
{
drgb[0] = GetRGB4(screen->ViewPort.ColorMap, RED_COLOR);
lower_shade(&drgb[0]); /* Make new grid colors darker than pieces */
drgb[1] = drgb[0];
lower_shade(&drgb[1]);
drgb[2] = drgb[1];
lower_shade(&drgb[2]);
}
else if((id & (GREEN | RED)) == RED) /* If red player loses... */
{
drgb[0] = GetRGB4(screen->ViewPort.ColorMap, GREEN_COLOR);
lower_shade(&drgb[0]); /* Make new grid colors darker than pieces */
drgb[1] = drgb[0];
lower_shade(&drgb[1]);
drgb[2] = drgb[1];
lower_shade(&drgb[2]);
}
else /* A draw */
{
drgb[0] = GetRGB4(screen->ViewPort.ColorMap, RED_COLOR);
lower_shade(&drgb[0]);
drgb[1] = GetRGB4(screen->ViewPort.ColorMap, GREEN_COLOR);
lower_shade(&drgb[1]);
drgb[2] = GetRGB4(screen->ViewPort.ColorMap, BACKGROUND);
}
victory_chord(TRUE); /* Play victory chord */
for(i=0; i<COLORSHADES; i++) /* Fade board to appropriate colors */
{
Delay(WAITTIME);
modify_victory_sound(1);
for(j=0; j<3; j++)
adjust_rgb(&rgb[j], drgb[j]);
set_color(DARK_SQUARE, rgb[0]);
set_color(LIGHT_SQUARE, rgb[1]);
set_color(BACKGROUND, rgb[2]);
}
dequeue_window();
release_mouse_buttons(); /* Wait for mouse button press */
/* Fade back to normal colors */
for(j=0; j<3; j++)
drgb[j] = rgb_save[j];
for(i=0; i<COLORSHADES; i++)
{
Delay(WAITTIME);
modify_victory_sound(-1);
for(j=0; j<3; j++)
adjust_rgb(&rgb[j], drgb[j]);
set_color(DARK_SQUARE, rgb[0]);
set_color(LIGHT_SQUARE, rgb[1]);
set_color(BACKGROUND, rgb[2]);
}
victory_chord(FALSE);
}
draw_back(x, y, highlight) /* Draws piece on background screen */
register int x, y, highlight;
{
register struct BitMap *save;
save = current_bitmap;
current_bitmap = &backup_bitmap; /* Temporarily change pointers */
draw_piece(x, y, highlight);
current_bitmap = save; /* Restore bitmap pointer */
}
draw_beam_segment(x, y, lxd, lyd) /* Draws a laser beam segment from center of grid square */
int x, y, lxd, lyd; /* (x, y) to (x + lxd, y + lyd). */
{
int cf, tx, ty, out;
register int sx, sy, dx, dy;
tx = x + lxd; ty = y + lyd; /* Get destination point of laser beam */
/* If beam is going out of bounds... */
if(tx < 0 || tx >= GRIDX || ty < 0 || ty >= GRIDY)
out = TRUE;
else out = FALSE;
if(lxd != 0 && lyd != 0) /* If beam is going at a diagonal... */
{ /* Optimize the diagonal routine to draw from one grid square to next without having to change colors at mid-point (faster) */
sx = x * GRIDSQUAREWIDTH + GRIDLEFT + GRIDSQUAREWIDTH / 2;
sy = y * GRIDSQUAREHEIGHT + GRIDTOP + GRIDSQUAREHEIGHT / 2;
if(out) /* If beam is going out of grid boundary... */
{
/* Set destination at half-way point so as not to draw out of
* grid boundary */
dx = sx + (1 + (GRIDSQUAREWIDTH / 2)) * lxd;
dy = sy + (1 + (GRIDSQUAREHEIGHT / 2)) * lyd;
}
else /* If beam is within grid boundary... */
{
dx = tx * GRIDSQUAREWIDTH + (GRIDSQUAREWIDTH / 2) + GRIDLEFT;
dy = ty * GRIDSQUAREHEIGHT + (GRIDSQUAREHEIGHT / 2) + GRIDTOP;
}
if(square_color(x, y) == DARK_SQUARE)
SetAPen(&screen->RastPort, LASER_DARK);
else SetAPen(&screen->RastPort, LASER_LIGHT);
Move(&screen->RastPort, (long)(x * GRIDSQUAREWIDTH + GRIDLEFT +
GRIDSQUAREWIDTH / 2), (long)(y * GRIDSQUAREHEIGHT + GRIDTOP +
GRIDSQUAREHEIGHT / 2));
Draw(&screen->RastPort, (long)dx, (long)dy);
return;
}
sx = x * GRIDSQUAREWIDTH + (GRIDSQUAREWIDTH / 2) + GRIDLEFT;
sy = y * GRIDSQUAREHEIGHT + (GRIDSQUAREHEIGHT / 2) + GRIDTOP;
/* Destination of half-way point */
dx = sx + (1 + (GRIDSQUAREWIDTH / 2)) * lxd;
dy = sy + (1 + (GRIDSQUAREHEIGHT / 2)) * lyd;
cf = square_color(x, y) == DARK_SQUARE? TRUE : FALSE;
if(cf) SetAPen(&screen->RastPort, LASER_DARK);
else SetAPen(&screen->RastPort, LASER_LIGHT);
Move(&screen->RastPort, (long)sx, (long)sy);
Draw(&screen->RastPort, (long)dx, (long)dy);
if(!out) /* If laser isn't going out of grid boundary... */
{
/* Make dest. of last segment the origin of this one (last half) */
sx = dx; sy = dy;
dx = sx + (GRIDSQUAREWIDTH / 2) * lxd;
dy = sy + (GRIDSQUAREHEIGHT / 2) * lyd;
if(cf) SetAPen(&screen->RastPort, LASER_LIGHT);
else SetAPen(&screen->RastPort, LASER_DARK);
Move(&screen->RastPort, (long)sx, (long)sy);
Draw(&screen->RastPort, (long)dx, (long)dy);
}
}
/* Draws a box with a shadow with the given color register */
draw_box(width, height, color_register)
register int width, height;
register long color_register;
{
SetAPen(&screen->RastPort, color_register);
SetDrMd(&screen->RastPort, JAM1);
RectFill(&screen->RastPort, (long)(SCREENX / 2 - width / 2),
(long)(SCREENY / 2 - height / 2), (long)(SCREENX / 2 +
width / 2), (long)(SCREENY / 2 + height / 2));
SetAPen(&screen->RastPort, BLACK); /* Draw box shadow */
Move(&screen->RastPort, (long)(SCREENX / 2 - width / 2 - 1),
(long)(SCREENY / 2 - height / 2 + 1));
Draw(&screen->RastPort, (long)(SCREENX / 2 - width / 2 - 1),
(long)(SCREENY / 2 + height / 2 + 1));
Draw(&screen->RastPort, (long)(SCREENX / 2 + width / 2 -1),
(long)(SCREENY / 2 + height / 2 + 1));
}
draw_icons()
{
draw_closed_disk(FALSE);
BltBitMap(&image_bitmap, (long)SP_QUITX1, (long)SP_QUITY1,
current_bitmap, (long)QUITX1, (long)QUITY1, (long)(QUITX2 - QUITX1),
(long)(QUITY2 - QUITY1), BLIT_11_MINTERM, -1L, NULL);
BltBitMap(&image_bitmap, (long)SP_RESTARTX1, (long)SP_RESTARTY1,
current_bitmap, (long)RESTARTX1, (long)RESTARTY1,
(long)(RESTARTX2 - RESTARTX1), (long)(RESTARTY2 - RESTARTY1),
BLIT_11_MINTERM, -1L, NULL);
BltBitMap(&image_bitmap, (long)SP_FIREX1, (long)SP_FIREY1,
current_bitmap, (long)FIREX1, (long)FIREY1, (long)(FIREX2 - FIREX1),
(long)(FIREY2 - FIREY1), BLIT_11_MINTERM, -1L, NULL);
BltBitMap(&image_bitmap, (long)SP_PASSX1, (long)SP_PASSY1,
current_bitmap, (long)PASSX1, (long)PASSY1, (long)(PASSX2 - PASSX1),
(long)(PASSY2 - PASSY1), BLIT_11_MINTERM, -1L, NULL);
BltBitMap(&image_bitmap, (long)SP_POSSIBLE_MOVESX1, (long)SP_POSSIBLE_MOVESY1,
current_bitmap, (long)POSSIBLE_MOVESX1, (long)POSSIBLE_MOVESY1,
(long)(POSSIBLE_MOVESX2 - POSSIBLE_MOVESX1),
(long)(POSSIBLE_MOVESY2 - POSSIBLE_MOVESY1), BLIT_11_MINTERM, -1L, NULL);
BltBitMap(&image_bitmap, (long)SP_LOSSX1, (long)SP_LOSSY1,
current_bitmap, (long)LOSSX1, (long)LOSSY1, (long)(LOSSX2 - LOSSX1),
(long)(LOSSY2 - LOSSY1), BLIT_11_MINTERM, -1L, NULL);
}
draw_closed_disk(audible) /* Draws a closed disk with optional sound */
register int audible;
{
if(audible) disk_close_sound();
BltBitMap(&image_bitmap, (long)SP_CLOSED_DISKX1, (long)SP_CLOSED_DISKY1,
current_bitmap, (long)DISKX1, (long)DISKY1, (long)(DISKX2 - DISKX1),
(long)(DISKY2 - DISKY1), BLIT_11_MINTERM, -1L, NULL);
}
draw_open_disk()
{
disk_open_sound();
BltBitMap(&image_bitmap, (long)SP_OPEN_DISKX1, (long)SP_OPEN_DISKY1,
current_bitmap, (long)DISKX1, (long)DISKY1, (long)(DISKX2 - DISKX1),
(long)(DISKY2 - DISKY1), BLIT_11_MINTERM, -1L, NULL);
}
set_color(reg, color)
register long reg;
register UWORD color;
{
SetRGB4(&screen->ViewPort, reg, RED_VALUE(color), GREEN_VALUE(color),
BLUE_VALUE(color));
}
clear_screen(bitmap) /* Clears PLANES number of planes in designated bitmap */
register struct BitMap *bitmap;
{
register int i;
for(i=0; i<PLANES; i++)
BltClear(bitmap->Planes[i], (long)SCREENBYTES, 0L);
}
flip_screens()
{
int class, code, qualifier, x, y;
if(current_bitmap == &primary_bitmap)
screen->ViewPort.RasInfo->BitMap = screen->RastPort.BitMap =
current_bitmap = window->RPort->BitMap = &backup_bitmap;
else
screen->ViewPort.RasInfo->BitMap = screen->RastPort.BitMap =
current_bitmap = window->RPort->BitMap = &primary_bitmap;
}
reset_view() /* Makes sure currently-viewed bitmap is primary bitmap */
{
current_bitmap = screen->ViewPort.RasInfo->BitMap =
screen->RastPort.BitMap = window->RPort->BitMap = &primary_bitmap;
MakeScreen(screen);
RethinkDisplay();
}
copy_screen(source, destination) /* Copies a source bitmap to destination */
register struct BitMap *source, *destination;
{
register int i;
for(i=0; i<PLANES; i++)
BltBitMap(source, 0L, 0L, destination, 0L, 0L,
(long)SCREENX, (long)SCREENY, BLIT_11_MINTERM, -1L, NULL);
}
new_view() /* Calls appropriate routines to display new view */
{
MakeScreen(screen);
RethinkDisplay();
}